package org.venipedia.ui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.SQLException;

import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

import org.venipedia.dbcore.jdbc.JdbcDatabase;
import org.venipedia.dbcore.jdbc.JdbcTable;
import org.venipedia.record.TableSelectionListener;
import org.venipedia.ui.jdbc.DatabaseLoginFrame;
import org.venipedia.ui.jdbc.TableSelectionFrame;
import org.venipedia.ui.jdbc.TableViewer;
import org.venipedia.ui.template.NewTemplateFrame;

import com.centerkey.utils.BareBonesBrowserLaunch;

public class VenipediaBot {

	private static final int STATUS_LENGTH = 5000;
	private JFrame frmVenipediabot;
	JDesktopPane desktop;

	private JLabel lblStatusBar;

	JdbcDatabase db;

	Timer timer;
	private JProgressBar progressBar;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		setLAF();
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					VenipediaBot window = new VenipediaBot();
					window.frmVenipediabot.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public VenipediaBot() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmVenipediabot = new JFrame();
		frmVenipediabot.setIconImage(Toolkit.getDefaultToolkit().getImage(
				VenipediaBot.class.getResource("/venicon.png")));
		frmVenipediabot.setTitle("VenipediaBot");
		frmVenipediabot.setBounds(100, 100, 947, 673);
		frmVenipediabot.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		desktop = new JDesktopPane();
		frmVenipediabot.getContentPane().add(desktop, BorderLayout.CENTER);

		JPopupMenu popupMenu = new JPopupMenu();
		addPopup(desktop, popupMenu);

		JMenu mnDatabase = new JMenu("Database");
		mnDatabase.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/database.png")));
		popupMenu.add(mnDatabase);

		JMenuItem mntmConnectToRemote = new JMenuItem(
				"Connect to remote database");
		mntmConnectToRemote.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				connectToRemoteDb();
			}
		});
		mntmConnectToRemote.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/database-network.png")));
		mnDatabase.add(mntmConnectToRemote);

		JMenu mnViewRecordTable = new JMenu("View record table");
		mnViewRecordTable.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/tables-stacks.png")));
		// popupMenu.add(mnViewRecordTable);

		JMenu mnTemplates = new JMenu("Templates");
		mnTemplates.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/blogs.png")));
		popupMenu.add(mnTemplates);

		JMenuItem mntmNewTemplate = new JMenuItem("New template");
		mntmNewTemplate.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/blog--plus.png")));
		mnTemplates.add(mntmNewTemplate);

		JMenuItem mntmTemplates = new JMenuItem("Templates");
		mntmTemplates.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/blogs.png")));
		mnTemplates.add(mntmTemplates);

		lblStatusBar = new JLabel("");
		lblStatusBar.setBounds(6, 0, 1184, 16);
		desktop.add(lblStatusBar);

		progressBar = new JProgressBar();
		progressBar.setMaximum(1000);
		frmVenipediabot.getContentPane().add(progressBar, BorderLayout.SOUTH);
		mntmTemplates.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showTemplates();
			}
		});
		mntmNewTemplate.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				createNewTemplate();
			}
		});

		JMenuBar menuBar = new JMenuBar();
		frmVenipediabot.setJMenuBar(menuBar);

		JMenu mnFile = new JMenu("File");
		mnFile.setMnemonic('F');
		menuBar.add(mnFile);

		JMenuItem mntmSaveDataXml = new JMenuItem("Save data to XML...");
		mntmSaveDataXml.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/disk-black.png")));
		mnFile.add(mntmSaveDataXml);
		mntmSaveDataXml.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				saveToXML();
			}
		});

		JSeparator separator_2 = new JSeparator();
		mnFile.add(separator_2);

		JMenu mnImport = new JMenu("Import");
		mnImport.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/database-import.png")));
		mnImport.setMnemonic('I');
		mnFile.add(mnImport);

		JMenuItem mntmKml = new JMenuItem("KML...");
		mntmKml.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/globe-green.png")));
		mnImport.add(mntmKml);
		mntmKml.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				importKml();
			}
		});

		JSeparator separator = new JSeparator();
		mnFile.add(separator);

		JMenuItem mntmExit = new JMenuItem("Exit");
		mntmExit.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/door-open-out.png")));
		mntmExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
				InputEvent.CTRL_MASK));
		mnFile.add(mntmExit);

		JMenu mnView = new JMenu("View");
		mnView.setMnemonic('V');
		menuBar.add(mnView);

		JMenuItem mntmViewRecordTable = new JMenuItem("Record table");
		mntmViewRecordTable.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/table.png")));
		mnView.add(mntmViewRecordTable);
		mntmViewRecordTable.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				viewRecordTable();
			}
		});

		JSeparator separator_1 = new JSeparator();
		mnView.add(separator_1);

		JMenuItem mntmVenipediaInWindow = new JMenuItem("Venipedia (in window)");
		mntmVenipediaInWindow.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/application-text-image.png")));
		mnView.add(mntmVenipediaInWindow);

		JMenuItem mntmVenipediaInBrowser = new JMenuItem(
				"Venipedia (in browser)");
		mntmVenipediaInBrowser.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/application-browser.png")));
		mnView.add(mntmVenipediaInBrowser);

		JMenu mnHelp = new JMenu("Help");
		mnHelp.setMnemonic('h');
		menuBar.add(mnHelp);

		JMenuItem mntmReportBug = new JMenuItem("Report bug");
		mntmReportBug.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/bug--exclamation.png")));
		mnHelp.add(mntmReportBug);
		mntmReportBug.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				BareBonesBrowserLaunch
						.openURL("http://code.google.com/p/venipedia-bot/issues/entry?template=Defect report from user");
			}
		});

		JMenuItem mntmAbout = new JMenuItem("About");
		mntmAbout.setIcon(new ImageIcon(VenipediaBot.class
				.getResource("/icons/balloon-ellipsis.png")));
		mnHelp.add(mntmAbout);
		mntmAbout.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				about();
			}
		});

		mntmVenipediaInBrowser.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				viewVenipediaInBrowser();
			}
		});

		mntmVenipediaInWindow.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				viewVenipediaInWindow();
			}
		});

		mntmExit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				exit();
			}
		});

		getProgressBar().setVisible(false);

		frmVenipediabot.setExtendedState(JFrame.MAXIMIZED_BOTH);

		setStatus("Ready.");
	}

	protected void connectToRemoteDb() {
		DatabaseLoginFrame f = new DatabaseLoginFrame(this);
		desktop.add(f);
	}

	public void setProgress(int prog) {
		JProgressBar bar = getProgressBar();
		bar.setVisible(true);
		if (prog < 0) {
			bar.setIndeterminate(true);
			return;
		} else {
			bar.setValue(prog);
			if (prog >= 1000)
				bar.setVisible(false);
		}
	}

	public void showErrorDialog(Exception ex) {
		ErrorFrame ef = new ErrorFrame(ex);
		desktop.add(ef);
		ef.setVisible(true);
	}

	public void viewVenipediaInBrowser() {
		BareBonesBrowserLaunch.openURL("http://www.venipedia.org/");
	}

	public void viewVenipediaInWindow() {
		SimpleBrowser browser = new SimpleBrowser("http://www.venipedia.org/");
		desktop.add(browser);
	}

	/**
	 * Pops up a spreadsheet containing the records in the given record type.
	 */
	public void viewRecordTable() {
		if (db == null) {
			JOptionPane
					.showMessageDialog(
							desktop,
							"No database currently in memory.\nWould you like to create a database?",
							"No database loaded",
							JOptionPane.INFORMATION_MESSAGE);
			return;
		}
		final VenipediaBot vb = this;
		try {
			new TableSelectionFrame(db, desktop, new TableSelectionListener() {
				public void tableSelected(JdbcTable t) {
					// RecordEditor ed = new RecordEditor(t, vb);
					// desktop.add(ed);
					TableViewer tv = new TableViewer(t, vb);
					desktop.add(tv);
				}
			});
		} catch (SQLException e) {
			showErrorDialog(e);
			e.printStackTrace();
		}
	}

	private void clearStatus() {
		lblStatusBar.setText("");
	}

	public void setStatus(final String status) {
		if (timer != null)
			timer.stop();
		Timer timer2 = new Timer(100, new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				lblStatusBar.setText(status);
			}
		});
		timer2.setInitialDelay(1);
		timer2.setRepeats(false);
		timer2.start();
		timer = new Timer(100, new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				clearStatus();
			}
		});
		timer.setInitialDelay(STATUS_LENGTH);
		timer.setRepeats(false);
		timer.start();
		System.out.println(status);
	}

	/**
	 * Pops open the box to start a KML import.
	 */
	public void importKml() {
		// ImportFrame impf = new ImportFrame(db, new KMLImporter(), desktop);
		// desktop.add(impf);
	}

	public void saveToXML() {
		// if (db == null) {
		// JOptionPane.showMessageDialog(desktop,
		// "No database in memory...\nNothing to save!",
		// "No database", JOptionPane.WARNING_MESSAGE);
		// return;
		// }
		// File file = null;
		// JFileChooser chooser = new JFileChooser();
		// chooser.setAcceptAllFileFilterUsed(false);
		// FileFilter filter = new FileTypeFilter("xml", "XML document");
		// chooser.setFileFilter(filter);
		//
		// int retval = chooser.showSaveDialog(desktop);
		// if (retval == JFileChooser.APPROVE_OPTION) {
		// file = chooser.getSelectedFile();
		// } else {
		// return;
		// }
		// try {
		// db.writeXMLToFile(file);
		// } catch (Exception e) {
		// JOptionPane.showMessageDialog(desktop,
		// "Could not save file -- \n\n" + e.toString(),
		// "Error saving file", JOptionPane.ERROR_MESSAGE);
		// }
	}

	public void exit() {
		System.exit(0);
	}

	public void about() {
		JOptionPane
				.showMessageDialog(
						frmVenipediabot,
						"VenipediaBot\nVersion 1.0\nCoded by Ryan Muller "
								+ "<ryan.muller@wpi.edu>\nOctober 10, 2011\n\nIcons (c) Yusuke Kamiyamane <p.yusukekamiyamane.com>"
								+ ".\nReleased under a Creative Commons Attribution 3.0 license.",
						"About VenipediaBot", JOptionPane.INFORMATION_MESSAGE);
	}

	/**
	 * Create a new template from scratch.
	 */
	public void createNewTemplate() {
		if (db == null) {
			JOptionPane
					.showMessageDialog(
							desktop,
							"The database is empty. Please connect to a database to create templates.",
							"Null Database", JOptionPane.WARNING_MESSAGE);
			return;
		}
		NewTemplateFrame f = new NewTemplateFrame();
		desktop.add(f);
	}

	public void showTemplates() {
		// new TemplateSelectionFrame(db, desktop);
	}

	public static void setLAF() {
		try {
			for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
				if ("Nimbus".equals(info.getName())) {
					UIManager.setLookAndFeel(info.getClassName());
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void addPopup(Component component, final JPopupMenu popup) {
		component.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}

			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}

			private void showMenu(MouseEvent e) {
				popup.show(e.getComponent(), e.getX(), e.getY());
			}
		});
	}

	public void setDb(JdbcDatabase db2) {
		db = db2;
	}

	public JProgressBar getProgressBar() {
		return progressBar;
	}
}
